package cn.merryyou.generator.service.utils;

import cn.merryyou.generator.config.GenConfig;
import cn.merryyou.generator.domain.BaseEntity;
import cn.merryyou.generator.domain.TableInfo;
import cn.merryyou.generator.service.GenInfo;
import cn.merryyou.generator.service.GenUtils;
import cn.merryyou.generator.util.DateUtils;
import cn.merryyou.generator.util.StringUtils;
import org.apache.velocity.VelocityContext;

import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.List;

public class GenInterMybatisPlus implements GenInterfaces {
    /**
     * 项目空间路径
     */
    private static final String PROJECT_PATH = getProjectPath();

    /**
     * BaseEntity中通用字段的名字集合
     */
    private static final String COMMON_COLUMNS = getCommonColumnNames();


    /**
     * mybatis空间路径
     */
    private static final String MYBATIS_PATH = "main/resources/mapper" ;

    /**
     * html空间路径
     */
    private static final String TEMPLATES_PATH = "main/resources/templates" ;

    @Override
    public VelocityContext getVelocityContext(GenInfo genInfo, TableInfo table) {
        // java对象数据传递到模板文件vm
        VelocityContext velocityContext = new VelocityContext();
        String packageName = genInfo.getJavaPackage();
        if (StringUtils.isEmpty(packageName)) {
            packageName = GenConfig.getPackageName();
        }
        velocityContext.put("tableName", table.getTableName());
        velocityContext.put("tableComment", GenUtils.replaceKeyword(table.getTableComment()));
        velocityContext.put("primaryKey", table.getPrimaryKey());
        velocityContext.put("className", table.getClassName());
        velocityContext.put("classname", table.getClassname());
        velocityContext.put("classname_lower", table.getClassname().toLowerCase());
        velocityContext.put("columns", table.getColumns());

        velocityContext.put("basePackage", packageName);//基础包名

        // 模块名
        String moduleName = genInfo.getModuleName();
        if (StringUtils.isEmpty(moduleName)) {
            moduleName = table.getClassname();
        }
        velocityContext.put("moduleName", moduleName);

        // 全包名
        if (StringUtils.isNotEmpty(genInfo.getModuleName())) {
            packageName += "." + genInfo.getModuleName();
        }
        velocityContext.put("package", packageName);

        velocityContext.put("author", GenConfig.getAuthor());
        velocityContext.put("datetime", DateUtils.getDate());
        //用来排除domain模板中的通用字段
        velocityContext.put("commonColumnNames", COMMON_COLUMNS);
        return velocityContext;

    }

    @Override
    public List<String> getTemplates(String style) {
        List<String> templates = new ArrayList<String>();
        templates.add("vm/" + style + "/java/domain.java.vm");
        templates.add("vm/" + style + "/java/Mapper.java.vm");
        templates.add("vm/" + style + "/java/Service.java.vm");
        templates.add("vm/" + style + "/java/ServiceImpl.java.vm");
        templates.add("vm/" + style + "/java/Controller.java.vm");
        templates.add("vm/" + style + "/xml/Mapper.xml.vm");
        templates.add("vm/" + style + "/html/list.html.vm");
        templates.add("vm/" + style + "/html/add.html.vm");
        templates.add("vm/" + style + "/html/edit.html.vm");
        templates.add("vm/" + style + "/sql/sql.vm");
        return templates;
    }

    @Override
    public String getFileName(GenInfo genInfo, String template, TableInfo table) {
        // 小写类名
        String classname = table.getClassname();
        // 大写类名
        String className = table.getClassName();

        String javaPath;
        if (StringUtils.isEmpty(genInfo.getJavaPath())) {
            javaPath = PROJECT_PATH;
        } else {
            javaPath = genInfo.getJavaPath();
        }

        if (!StringUtils.isEmpty(genInfo.getModuleName())) {
            javaPath += "/" + genInfo.getModuleName() + "/" ;
        }

        String mybatisPath = MYBATIS_PATH + "/" + genInfo.getModuleName() + "/" + className;
        String htmlPath = TEMPLATES_PATH + "/" + genInfo.getModuleName() + "/" + classname;

        if (template.contains("domain.java.vm")) {
            return javaPath + "domain" + "/" + className + ".java" ;
        }

        if (template.contains("Mapper.java.vm")) {
            return javaPath + "mapper" + "/" + className + "Mapper.java" ;
        }

        if (template.contains("Service.java.vm")) {
            return javaPath + "service" + "/" + "I" + className + "Service.java" ;
        }

        if (template.contains("ServiceImpl.java.vm")) {
            return javaPath + "service" + "/impl/" + className + "ServiceImpl.java" ;
        }

        if (template.contains("Controller.java.vm")) {
            return javaPath + "controller" + "/" + className + "Controller.java" ;
        }

        if (template.contains("Mapper.xml.vm")) {
            return mybatisPath + "Mapper.xml" ;
        }

        if (template.contains("list.html.vm")) {
            return htmlPath + "/" + classname + ".html" ;
        }
        if (template.contains("add.html.vm")) {
            return htmlPath + "/" + "add.html" ;
        }
        if (template.contains("edit.html.vm")) {
            return htmlPath + "/" + "edit.html" ;
        }
        if (template.contains("sql.vm")) {
            return classname + "Menu.sql" ;
        }
        return null;
    }

    /**
     * 获取BaseEntity中通用字段的名字集合
     */
    private static String getCommonColumnNames() {
        StringBuilder names = new StringBuilder();
        Field[] fields = BaseEntity.class.getDeclaredFields();
        for (Field field : fields) {
            if (Modifier.PROTECTED == field.getModifiers()) {
                names.append(field.getName() + ",");
            }
        }
        return names.toString();
    }


    public static String getProjectPath() {
        String packageName = GenConfig.getPackageName();
        StringBuffer projectPath = new StringBuffer();
        projectPath.append("main/java/");
        projectPath.append(packageName.replace(".", "/"));
        projectPath.append("/");
        return projectPath.toString();
    }
}
